package com.refusea.train.config.mvc

import com.refusea.train.domain.ex.BizEx
import com.refusea.train.domain.rsp.Rsp
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import org.springframework.beans.TypeMismatchException
import org.springframework.http.HttpStatus
import org.springframework.http.converter.HttpMessageNotReadableException
import org.springframework.web.bind.annotation.ExceptionHandler
import org.springframework.web.bind.annotation.ResponseStatus
import org.springframework.web.bind.annotation.RestControllerAdvice
import org.springframework.web.servlet.NoHandlerFoundException
import org.springframework.web.servlet.resource.NoResourceFoundException

@RestControllerAdvice
class GlobalExceptionHandler {

    private val log: Logger = LoggerFactory.getLogger(GlobalExceptionHandler::class.java)

    private final val err400 = Rsp(400, "Bad Request", null)
    private final val err404 = Rsp(404, "Not Found", null)

    @ExceptionHandler(NoResourceFoundException::class)
    @ResponseStatus(HttpStatus.NOT_FOUND)
    fun handleNoResourceFoundException(ex: NoResourceFoundException) {
        log.error(ex.message)
    }

    @ExceptionHandler(
        HttpMessageNotReadableException::class,
        TypeMismatchException::class,
        IllegalArgumentException::class
    )
    fun handleBadRequest(ex: Exception): Rsp {
        log.error(ex.message)
        return err400
    }

    @ExceptionHandler(NoHandlerFoundException::class)
    fun handleNotFound(): Rsp {
        return err404
    }

    @ExceptionHandler(BizEx::class)
    fun handleBizEx(ex: BizEx): Rsp {
        log.warn(ex.message)
        return Rsp(500, ex.message, null)
    }

    @ExceptionHandler(Exception::class)
    fun handleException(ex: Exception): Rsp {
        log.error(ex.message, ex)
        return Rsp(500, "Internal Server Error: " + ex.message, null)
    }

}
